package com.alibaba.citrus.cr.sales.plan.facade.service.salesplan.publish;

import com.alibaba.citrus.cr.common.annotation.EpochTransactional;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.annotation.ProcessInvoker;
import com.alibaba.citrus.cr.common.exception.ActivityException;
import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.common.lock.RedisLock;
import com.alibaba.citrus.cr.common.util.CalculatePercentage;
import com.alibaba.citrus.cr.sales.plan.annotation.CommonRedisLock;
import com.alibaba.citrus.cr.sales.plan.api.salesplan.SalesPlanLineWriteService;
import com.alibaba.citrus.cr.sales.plan.api.salesplan.SalesPlanQueryService;
import com.alibaba.citrus.cr.sales.plan.contants.SalesPlanConstants;
import com.alibaba.citrus.cr.sales.plan.contants.SalesPlanLockKey;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.SalesPlanAdjustDetailBatchQueryRequest;
import com.alibaba.citrus.cr.sales.plan.functions.salesplan.SalesPlanLineAbility;
import com.alibaba.citrus.cr.sales.plan.functions.salesplan.adjust.SalesPlanAdjustDetailAbility;
import com.alibaba.citrus.cr.sales.plan.functions.salesplan.adjust.SalesPlanAdjustDetailEntity;
import com.alibaba.citrus.cr.sales.plan.model.SalesPlanLineStatusEnum;
import com.alibaba.citrus.cr.sales.plan.model.enums.SalesPlanCheckStatusEnum;
import com.alibaba.citrus.cr.sales.plan.model.enums.SalesPlanModelEnum;
import com.alibaba.citrus.cr.sales.plan.model.enums.SalesPlanStatusEnum;
import com.alibaba.citrus.cr.sales.plan.model.enums.SalesStatBizTypeEnum;
import com.alibaba.citrus.cr.sales.plan.model.enums.StatPoolTypeEnum;
import com.alibaba.citrus.cr.sales.plan.model.features.SalesPlanAdjustDetailFeatures;
import com.alibaba.citrus.cr.sales.plan.repository.SalesPlanAdjustDetailRepository;
import com.alibaba.citrus.cr.sales.plan.repository.SalesPlanLineRepository;
import com.alibaba.citrus.cr.sales.plan.repository.SalesPlanRepository;
import com.alibaba.citrus.cr.sales.plan.repository.SalesPlanScItemExtendRepository;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanAdjustDetailSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanLineSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanPublishSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanScItemExtendSDO;
import com.alibaba.citrus.cr.sales.plan.api.salesplan.publish.SalesPlanPublishWriteService;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.DispatchPlanScItemRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.EditSalesPlanAdjustDetailRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.EditSalesPlanPublishRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.PageQueryPlanAdjustDetailRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.PageQueryPlanLineRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.QueryPlanAdjustDetailRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.QueryPlanScItemExtendRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.QuerySalesPlanLineRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.QuerySalesPlanRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.SalesPlanBatchQueryRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.SalesPlanDetailBatchQueryRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.UpdateAdjustCountRequest;
import com.alibaba.citrus.cr.sales.plan.facade.service.SalesPlanCommonService;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.message.ErrorMessage;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.middleware.cache.runtime.service.EpochCacheService;
import com.alibaba.lattice2.epoch.middleware.mq.runtime.EpochMessageService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.contants.BcOrderConstants;
import com.epoch.app.bcorder.sales_plan.planscitemextend.dto.BatchQueryRequest;
import com.epoch.app.bcorder.sales_plan.planscitemextend.model.PlanScItemExtend;
import com.epoch.app.bcorder.sales_plan.planscitemextend.service.PlanScItemExtendService;
import com.epoch.app.bcorder.sales_plan.salesplanadjustdetail.dto.BatchQueryDetailByIdsRequest;
import com.epoch.app.bcorder.sales_plan.salesplanadjustdetail.dto.BatchQueryDetailByIdsResponse;
import com.epoch.app.bcorder.sales_plan.salesplanadjustdetail.model.SalesPlanAdjustDetail;
import com.epoch.app.bcorder.sales_plan.salesplanadjustdetail.service.SalesPlanAdjustDetailService;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class SalesPlanPublishWriteServiceImpl implements SalesPlanPublishWriteService {

    private static final Log log = Log.getLogger(SalesPlanPublishWriteServiceImpl.class);

    @Resource
    private SalesPlanRepository salesPlanRepository;

    @Resource
    private SalesPlanScItemExtendRepository salesPlanScItemExtendRepository;

    @Resource
    private SalesPlanLineRepository salesPlanLineRepository;

    @Resource
    private SalesPlanCommonService salesPlanCommonService;

    @Resource
    private SalesPlanAdjustDetailRepository salesPlanAdjustDetailRepository;

    @Resource
    private EpochMessageService epochMessageService;

    @Resource
    private SalesPlanLineWriteService salesPlanLineWriteService;

    @Resource
    private SalesPlanQueryService salesPlanQueryService;

    @Resource
    private SalesPlanLineAbility salesPlanLineAbility;

    @Resource
    private SalesPlanAdjustDetailAbility salesPlanAdjustDetailAbility;

    @Resource
    private SalesPlanAdjustDetailService salesPlanAdjustDetailService;

    @Resource
    private PlanScItemExtendService planScItemExtendService;

    @Resource
    private EpochCacheService epochCacheService;

    /**
     * 计划明细page_size
     */
    private static final Integer SALES_PLAN_LIN_PAGE_SIZE = 500;

    private static final int ZERO = 0;

    private static final int LIMIT = 1000;

    private static final int DEFAULT_PAGE_SIZE = 1000;

    @Override
    @FacadeInvoker
    public Result<Boolean> batchCreatePlanScItemExtend(List<SalesPlanScItemExtendSDO> createList) {
        if (CollectionUtils.isEmpty(createList)) {
            log.warn("SalesPlanPublishWriteServiceImpl.batchCreatePlanScItemExtend request isEmpty");
            return Result.success(true);
        }
        Boolean aBoolean = salesPlanScItemExtendRepository.batchCreatePlanScItemExtend(createList);
        return Result.success(aBoolean);
    }

    /**
     * 生成部门回复量
     * <p>
     * // 0、基本参数校验
     * // 1、月度计划校验（校验存在和状态处于待发布状态）
     * // 2、查询业务单元的货品回复量
     * // 3、业务单元的货品回复量和提报量比较（供大于求，按原提报量回复部门回复量和任务量）
     * // 4、求大于供的情况
     * //   4.1 查询业务单元下的月度计划策略
     * //   4.2 根据销售组织策略占比，计算销售组织的回复量和任务量
     * //   4.3 在销售组织下，根据下属部门策略，循环计算部门的回复量和任务量
     * // 5、批量添加到extend表中
     *
     * @param dispatchPlanScItemRequest
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Boolean> dispatchPlanScItemForDepartment(DispatchPlanScItemRequest dispatchPlanScItemRequest) {
        try (RedisLock lock = new RedisLock(BcOrderConstants.REDIS_CACHE_CODE(), SalesPlanLockKey.getPlanPublishDepartmentLockKey(dispatchPlanScItemRequest.getPlanId()))) {
            boolean locked = lock.lock();
            if (!locked) {
                log.error("SalesPlanStatServiceImpl#planCollect.getLock.fail planId=" + dispatchPlanScItemRequest.getPlanId());
                return Result.fail("OTS-02-006-00-16-006", "部门任务量正在生成中，请稍后重试");
            }
            String resolveFlag = epochCacheService.get(BcOrderConstants.REDIS_CACHE_CODE(), SalesPlanConstants.getDispatchPlanScItemForDepartmentKey(dispatchPlanScItemRequest.getPlanId()));
            if (SalesPlanConstants.CACHE_FLAG.equals(resolveFlag)) {
                return Result.success(null, "部门任务量正在生成中，请稍待");
            }
            epochCacheService.put(BcOrderConstants.REDIS_CACHE_CODE(), SalesPlanConstants.getDispatchPlanScItemForDepartmentKey(dispatchPlanScItemRequest.getPlanId()), SalesPlanConstants.CACHE_FLAG, 600L, TimeUnit.SECONDS);
            String message = JSONObject.toJSONString(dispatchPlanScItemRequest);
            Boolean result = epochMessageService.sendMessage("sales_plan_department_resolve_message", "CR_SALES_PLAN_V2", "DEPARTMENT_TASK_RESOLVE", message);
            log.info("月度计划部门任务量分解发送消息返回结果:{}", result);
        } catch (Exception e) {
            log.error("SalesPlanPublishWriteServiceImpl#dispatchPlanScItemForDepartment_fail  月度计划部门任务量分解发送消息异常", e);
        }
        return Result.success(null, "部门任务量分解程序已开启，已在后台加速处理，请稍后查看处理结果");
    }

    /**
     * 生成客户回复量
     * // 0、相关参数校验
     * // 1、查询该月度计划下的所有部门回复量，任务量
     * // 2、查询部门维度下的月度计划明细
     * // 3、根据部门回复量和任务量，计算客户回复量和任务量
     * // 4、更新月度计划明细数据
     *
     * @param dispatchPlanScItemRequest
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Boolean> dispatchPlanScItemForCustomer(DispatchPlanScItemRequest dispatchPlanScItemRequest) {
        try (RedisLock lock = new RedisLock(BcOrderConstants.REDIS_CACHE_CODE(), SalesPlanLockKey.getDispatchPlanScItemForCustomerLockKey(dispatchPlanScItemRequest.getPlanId()))) {
            boolean locked = lock.lock();
            if (!locked) {
                log.error("SalesPlanPublishWriteServiceImpl#dispatchPlanScItemForCustomer.getLock.fail planId=" + dispatchPlanScItemRequest.getPlanId());
                return Result.fail("OTS-02-006-00-16-006", "正在生成客户回复量中，请稍后重试");
            }
            String resolveFlag = epochCacheService.get(BcOrderConstants.REDIS_CACHE_CODE(), SalesPlanConstants.getDispatchPlanScItemForCustomerKey(dispatchPlanScItemRequest.getPlanId()));
            if (SalesPlanConstants.CACHE_FLAG.equals(resolveFlag)) {
                return Result.success(null, "客户任务量正在生成中，请稍待");
            }
            epochCacheService.put(BcOrderConstants.REDIS_CACHE_CODE(), SalesPlanConstants.getDispatchPlanScItemForCustomerKey(dispatchPlanScItemRequest.getPlanId()), SalesPlanConstants.CACHE_FLAG, 900L, TimeUnit.SECONDS);
            String message = JSONObject.toJSONString(dispatchPlanScItemRequest);
            Boolean result = epochMessageService.sendMessage("sales_plan_customer_resolve_message", "CR_SALES_PLAN_V2", "CUSTOMER_TASK_RESOLVE", message);
            log.info("月度计划客户任务量分解发送消息返回结果:{}", result);
        } catch (Exception e) {
            log.error("SalesPlanPublishWriteServiceImpl#dispatchPlanScItemForCustomer_fail  月度计划客户任务量分解发送消息异常", e);
        }
        return Result.success(null, "客户任务量分解程序已开启，已在后台加速处理，请稍后查看处理结果");
    }

    /**
     * 计划调整生成客户调整任务量
     * 1、基本参数校验
     * 2、查询业务单元调整的扩展表（extend）
     * 3、遍历每一个货品
     * 4、比较提报量和调整量的大小（调整量大于等于提报量，按照提报量回复）
     * 4.1 调整量小于提报量
     * 4.2 计划货品调整量大于0
     * 4.2.1 优先回复客户负值的调整量，在按比例回复正值的客户调整量
     * 4.3 计划货品调整量小于0
     * 4.3.1 优先回复客户正值的调整量，在按比例回复负值的客户调整量
     * 4.4 计划货品调整量小于0
     * 4.4.1 按客户调整提报量回复调整回复量
     * 5 更新明细表（调整维度 ）
     * 6 更新状态
     * @param dispatchPlanScItemRequest
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Boolean> dispatchPlanScItemForAdjust(DispatchPlanScItemRequest dispatchPlanScItemRequest) {
        try (RedisLock lock = new RedisLock(BcOrderConstants.REDIS_CACHE_CODE(), SalesPlanLockKey.getDispatchPlanScItemForAdjustLockKey(dispatchPlanScItemRequest.getAdjustId()))) {
            boolean locked = lock.lock();
            if (!locked) {
                log.error("SalesPlanPublishWriteServiceImpl#dispatchPlanScItemForAdjust.getLock.fail adjustId=" + dispatchPlanScItemRequest.getAdjustId());
                return Result.fail("OTS-02-006-00-16-006", "正在生成客户调整任务量中，请稍后重试");
            }
            String resolveFlag = epochCacheService.get(BcOrderConstants.REDIS_CACHE_CODE(), SalesPlanConstants.getDispatchPlanScItemForCustomerAdjustKey(dispatchPlanScItemRequest.getAdjustId()));
            if (SalesPlanConstants.CACHE_FLAG.equals(resolveFlag)) {
                return Result.success(null, "客户调整任务量正在生成中，请稍待");
            }
            epochCacheService.put(BcOrderConstants.REDIS_CACHE_CODE(), SalesPlanConstants.getDispatchPlanScItemForCustomerAdjustKey(dispatchPlanScItemRequest.getAdjustId()), SalesPlanConstants.CACHE_FLAG, 900L, TimeUnit.SECONDS);
            String message = JSONObject.toJSONString(dispatchPlanScItemRequest);
            Boolean result = epochMessageService.sendMessage("sales_plan_adjust_customer_resolve_message", "CR_SALES_PLAN_V2", "CUSTOMER_ADJUST_TASK_RESOLVE", message);
            log.info("月度计划调整客户任务量分解发送消息返回结果:{}", result);
        } catch (FacadeException e) {
            log.error("SalesPlanPublishWriteServiceImpl#dispatchPlanScItemForAdjust_fail  发生消息异常", e);
        }
        return Result.success(null, "客户调整任务量分解程序已开启，已在后台加速处理，请稍后查看处理结果");
    }

    /**
     * 调整发布客户任务量
     * 0、基本参数校验
     * 1、查询调整中的调整明细
     * 2、找到对应的月度计划明细（调整明细有plan_detail_id）
     * 3、将月度计划明细的调整量更新
     *
     * @param dispatchPlanScItemRequest
     * @return
     */
    @Override
    @FacadeInvoker
    @EpochTransactional(appCode="bc_order", dataSourceCode = "cr_ots", dataSourceType = "app")
    @CommonRedisLock(redisLockPrefix = SalesPlanLockKey.PUBLISH_PLAN_SC_ITEM_ADJUST_PREFIX)
    public Result<Boolean> publishPlanScItemForAdjust(DispatchPlanScItemRequest dispatchPlanScItemRequest) {
        log.info("publishPlanScItemForAdjust_dispatchPlanScItemRequest_request {}",JSONObject.toJSONString(dispatchPlanScItemRequest));
        // 1、相关参数校验
        String adjustId = dispatchPlanScItemRequest.getAdjustId();
        if (StringUtils.isBlank(adjustId)) {
            throw new ActivityException("OTS-02-004-01-15-018");
        }
        SalesPlanSDO salesPlanSDO = salesPlanCommonService.checkSalesPlan(adjustId);
        Integer planId = salesPlanSDO.getParentId();
        log.info("publishPlanScItemForAdjust_checkSalesPlan_result {}",JSONObject.toJSONString(salesPlanSDO));
        // 2、查询调整中的调整明细和计划明细
        List<SalesPlanLineSDO> salesPlanLineSDOList = Lists.newArrayList();
        List<SalesPlanAdjustDetailSDO> salesPlanAdjustDetailSDOList = fetchSalesPlanAdjustDetail(adjustId, salesPlanSDO.getOrgBusinessUnitCode(), salesPlanLineSDOList);
        log.info("publishPlanScItemForAdjust_fetchSalesPlanAdjustDetail_result {}",JSONObject.toJSONString(salesPlanSDO));
        // adjustDetailMap key:planDetailId value:SalesPlanAdjustDetailSDO
        Map<Long, SalesPlanAdjustDetailSDO> adjustDetailMap =
                salesPlanAdjustDetailSDOList.stream().collect(Collectors.toMap(SalesPlanAdjustDetailSDO::getPlanDetailId, item -> item));

        // 3、遍历月度计划明细,并修改
        salesPlanLineSDOList.forEach(salesPlanLineSDO -> {
            SalesPlanLineSDO editSalesPlanLineSDO = SalesPlanLineSDO.builder().build();
            BeanUtils.copyProperties(salesPlanLineSDO, editSalesPlanLineSDO);
            Long planDetailId = salesPlanLineSDO.getId();
            // 通过明细id拿到调整明细信息
            SalesPlanAdjustDetailSDO salesPlanAdjustDetailSDO = adjustDetailMap.get(planDetailId);
            // 上旬调整回复量
            Integer monthFirstAdjustReturnCount = salesPlanAdjustDetailSDO.getMonthFirstAdjustReturnCount();
            // 中旬调整回复量
            Integer monthMiddleAdjustReturnCount = salesPlanAdjustDetailSDO.getMonthMiddleAdjustReturnCount();
            // 下旬调整回复量
            Integer monthLastAdjustReturnCount = salesPlanAdjustDetailSDO.getMonthLastAdjustReturnCount();

            // 发布客户调整量时，同步更新调整明细的满足度
            Integer adjustReturnCount = monthFirstAdjustReturnCount + monthMiddleAdjustReturnCount + monthLastAdjustReturnCount;
            // 折前满足度=（任务量+调整提报量）*货品常规价
            Integer taskAdjustCount = salesPlanAdjustDetailSDO.getTaskCount() + adjustReturnCount;
            Long costInsuranceFreight = Objects.nonNull(salesPlanAdjustDetailSDO.getCostInsuranceFreight()) ? salesPlanAdjustDetailSDO.getCostInsuranceFreight() : 0;
            Long outboundPrice = Optional.ofNullable(salesPlanAdjustDetailSDO.getOutboundPrice()).orElse(0L);
            long notBeforeContractSatisfactionMoney = taskAdjustCount * costInsuranceFreight;
            long beforeContractSatisfactionMoney = salesPlanAdjustDetailSDO.getTaskCount() * costInsuranceFreight;

            // 到岸折前金额
            long beforeAdjustMonthOutboundMoney = taskAdjustCount * outboundPrice;
            salesPlanAdjustDetailSDO.setBeforeMonthOutboundMoney(beforeAdjustMonthOutboundMoney);
            // 到岸折后金额 到岸折后金额=到岸折前金额*(1-预估价格折扣率)
            salesPlanAdjustDetailSDO.calculateMonthOutboundMoney(salesPlanSDO.getEstimateDiscount());

            // 折前任务金额
            salesPlanAdjustDetailSDO.setBeforeTaskMoney(beforeContractSatisfactionMoney);
            BigDecimal beforeContractSatisfaction = CalculatePercentage.retainTwo(notBeforeContractSatisfactionMoney, salesPlanAdjustDetailSDO.getBeforeMonthContractMoney());
            salesPlanAdjustDetailSDO.setBeforeContractSatisfaction(beforeContractSatisfaction);
            // 折后满足度=（任务量+调整提报量）*货品常规价*（1-预估价格折扣率）
            BigDecimal multiply = salesPlanSDO.getEstimateDiscount().multiply(new BigDecimal("0.01").setScale(2, RoundingMode.HALF_UP));
            BigDecimal subtract = new BigDecimal(1).subtract(multiply);
            BigDecimal contractSatisfactionMoney = new BigDecimal(taskAdjustCount).multiply(new BigDecimal(costInsuranceFreight)).multiply(subtract);
            // 折后任务金额
            salesPlanAdjustDetailSDO.calculateTaskMoney(salesPlanSDO.getEstimateDiscount());
            BigDecimal contractSatisfaction = CalculatePercentage.retainTwoBigDecimal(contractSatisfactionMoney, new BigDecimal(salesPlanAdjustDetailSDO.getMonthContractMoney()));
            salesPlanAdjustDetailSDO.setContractSatisfaction(contractSatisfaction);
            // 折前调整金额
            long beforeAdjustMoney = adjustReturnCount * costInsuranceFreight;
            salesPlanAdjustDetailSDO.setBeforeAdjustMoney(beforeAdjustMoney);
            // 折后调整金额
            salesPlanAdjustDetailSDO.calculateAdjustMoney(salesPlanSDO.getEstimateDiscount());
            salesPlanAdjustDetailRepository.edit(salesPlanAdjustDetailSDO);
            // 旧的上旬调整总量
            Integer monthFirstAdjustTotalCountOld = salesPlanLineSDO.getMonthFirstAdjustTotalCount();
            // 旧的中旬调整总量
            Integer monthMiddleAdjustTotalCountOld = salesPlanLineSDO.getMonthMiddleAdjustTotalCount();
            // 旧的下旬调整总量
            Integer monthLastAdjustTotalCountOld = salesPlanLineSDO.getMonthLastAdjustTotalCount();

            // 旧的上旬调整量
            Integer monthFirstAdjustCountOld = salesPlanLineSDO.getMonthFirstAdjustCount();
            // 旧的中旬调整量
            Integer monthMiddleAdjustCountOld = salesPlanLineSDO.getMonthMiddleAdjustCount();
            // 旧的下旬调整量
            Integer monthLastAdjustCountOld = salesPlanLineSDO.getMonthLastAdjustCount();

            // 重新计算上中下询和总任务量 （原任务量+调整回复量）
            int monthFirstTaskCountNew = editSalesPlanLineSDO.getMonthFirstTaskCount() + monthFirstAdjustReturnCount;
            editSalesPlanLineSDO.setMonthFirstTaskCount(monthFirstTaskCountNew);
            int monthMiddleTaskCountNew = editSalesPlanLineSDO.getMonthMiddleTaskCount() + monthMiddleAdjustReturnCount;
            editSalesPlanLineSDO.setMonthMiddleTaskCount(monthMiddleTaskCountNew);
            int monthLastTaskCountNew = editSalesPlanLineSDO.getMonthLastTaskCount() + monthLastAdjustReturnCount;
            editSalesPlanLineSDO.setMonthLastTaskCount(monthLastTaskCountNew);
            editSalesPlanLineSDO.setTaskCount(monthFirstTaskCountNew + monthMiddleTaskCountNew + monthLastTaskCountNew);

//            // 到岸折前金额 xxx     计划量*outboundPrice
//            long beforeLinMonthOutboundMoney = editSalesPlanLineSDO.getTaskCount() * outboundPrice;
//            editSalesPlanLineSDO.setBeforeMonthOutboundMoney(beforeLinMonthOutboundMoney);
//            // 到岸折后金额 到岸折后金额=到岸折前金额*(1-预估价格折扣率)
//            editSalesPlanLineSDO.calculateMonthOutboundMoney(salesPlanSDO.getEstimateDiscount());

            // 更新月度计划明细表的调整回复总量、调整回复量（0）和调整提报量（0）
            editSalesPlanLineSDO.setMonthFirstAdjustTotalCount(monthFirstAdjustTotalCountOld + salesPlanAdjustDetailSDO.getMonthFirstAdjustTotalCount());
            editSalesPlanLineSDO.setMonthFirstAdjustCount(monthFirstAdjustCountOld + salesPlanAdjustDetailSDO.getMonthFirstAdjustTotalCount());
            editSalesPlanLineSDO.setMonthFirstAdjustReturnCount(0);
            editSalesPlanLineSDO.setMonthMiddleAdjustTotalCount(monthMiddleAdjustTotalCountOld + salesPlanAdjustDetailSDO.getMonthMiddleAdjustTotalCount());
            editSalesPlanLineSDO.setMonthMiddleAdjustCount(monthMiddleAdjustCountOld + salesPlanAdjustDetailSDO.getMonthFirstAdjustTotalCount());
            editSalesPlanLineSDO.setMonthMiddleAdjustReturnCount(0);
            editSalesPlanLineSDO.setMonthLastAdjustTotalCount(monthLastAdjustTotalCountOld + salesPlanAdjustDetailSDO.getMonthLastAdjustTotalCount());
            editSalesPlanLineSDO.setMonthLastAdjustCount(monthLastAdjustCountOld + salesPlanAdjustDetailSDO.getMonthFirstAdjustTotalCount());
            editSalesPlanLineSDO.setMonthLastAdjustReturnCount(0);
            // 月度调整量，折后金额，折前金额置为0
            editSalesPlanLineSDO.setAdjustCount(0);
            editSalesPlanLineSDO.setAdjustMoney(0L);
            editSalesPlanLineSDO.setBeforeAdjustMoney(0L);

            // 计算折前任务金额
            Long costInsuranceFreight1 = Objects.nonNull(editSalesPlanLineSDO.getCostInsuranceFreight()) ? editSalesPlanLineSDO.getCostInsuranceFreight() : 0;
            editSalesPlanLineSDO.setBeforeTaskMoney(editSalesPlanLineSDO.getTaskCount() * costInsuranceFreight1);
            // 计算折后任务金额
            editSalesPlanLineSDO.calculateTaskMoney(salesPlanSDO.getEstimateDiscount());
            log.info("publishPlanScItemForAdjust_editSalesPlanLineSDO {}",JSONObject.toJSONString(editSalesPlanLineSDO));
            salesPlanLineRepository.edit(editSalesPlanLineSDO);
        });

        // 发布客户调整回复量时，修改调整任务status的状态
        SalesPlanSDO updateStatusSalesPlanSDO = new SalesPlanSDO();
        updateStatusSalesPlanSDO.setStatus(SalesPlanStatusEnum.PUBLISHED.getCode());
        updateStatusSalesPlanSDO.setId(Long.valueOf(adjustId));
        updateStatusSalesPlanSDO.setGmtModified(new Date());
        salesPlanRepository.editSalesPlan(updateStatusSalesPlanSDO);

        // 发布客户调整回复量时，修改原计划任务status的状态
        SalesPlanSDO updateStatusSalesPlanSDONew = new SalesPlanSDO();
        updateStatusSalesPlanSDONew.setStatus(SalesPlanStatusEnum.PUBLISHED.getCode());
        updateStatusSalesPlanSDONew.setId(Long.valueOf(planId));
        updateStatusSalesPlanSDONew.setGmtModified(new Date());
        salesPlanRepository.editSalesPlan(updateStatusSalesPlanSDONew);

        // 发布时要更新公司调整量的折前折后任务金额
        updatePlanScItemExtendTaskMoney(salesPlanSDO, adjustId);

        try {
            // 发消息，触发汇总
            log.info("publishPlanScItemForAdjust_salesPlanCollectListener{}", planId.toString());
            Boolean aBoolean = epochMessageService.sendMessage("sales_plan_publish_message", "CR_SALES_PLAN_V2", "salesPlan_collect", "#"+planId);
        } catch (Exception e) {
            log.error("发布客户调整量触发汇总消息发送异常", e);
        }

        return Result.success(true);
    }

    /**
     * 编辑部门回复量（失焦保存）
     * //0、校验每个货品的该部门修改的回复量量加上其他部门的回复量，是否大于分子公司的回复量总和
     * //1、修改上中下的回复量
     * //2、计算相关数量
     *
     * @param editSalesPlanPublishRequest
     * @return
     */
    @Override
    @FacadeInvoker
    @CommonRedisLock(redisLockPrefix = SalesPlanLockKey.EDIT_SALES_PLAN_DEPARTMENT_PUBLISH_PREFIX)
    public Result<SalesPlanScItemExtendSDO> editSalesPlanPublish(EditSalesPlanPublishRequest editSalesPlanPublishRequest) {
        // 0、校验每个货品的该部门修改的回复量量加上其他部门的回复量，是否大于分子公司的回复量总和
        // 1、修改上中下的回复量
        // 2、计算相关数量
        SalesPlanScItemExtendSDO salesPlanPublishSDO = salesPlanScItemExtendRepository.queryById(editSalesPlanPublishRequest.getId());
        if (salesPlanPublishSDO == null) {
            throw new FacadeException("OTS-02-004-01-15-031");
        }
        editSalesPlanPublishRequestConverter(salesPlanPublishSDO, editSalesPlanPublishRequest);

        // 校验任务量
        checkDepartmentTaskCount(salesPlanPublishSDO, editSalesPlanPublishRequest);

        Boolean update = salesPlanScItemExtendRepository.editSalesPlanScItemExtend(salesPlanPublishSDO);
        if (update) {
            return Result.success(salesPlanScItemExtendRepository.queryById(editSalesPlanPublishRequest.getId()));
        }
        return null;
    }

    @Override
    @ProcessInvoker
    public Result<SalesPlanScItemExtendSDO> editSalesPlanPublishForImport(EditSalesPlanPublishRequest editSalesPlanPublishRequest) {
        // 0、校验每个货品的该部门修改的回复量量加上其他部门的回复量，是否大于分子公司的回复量总和
        //1、修改上中下的回复量
        //2、计算相关数量
        SalesPlanScItemExtendSDO salesPlanPublishSDO = salesPlanScItemExtendRepository.queryById(editSalesPlanPublishRequest.getId());
        if (salesPlanPublishSDO == null) {
            throw new FacadeException("OTS-02-004-01-15-031");
        }
        editSalesPlanPublishRequestConverter(salesPlanPublishSDO, editSalesPlanPublishRequest);

        // 校验任务量
//        checkDepartmentTaskCount(salesPlanPublishSDO, editSalesPlanPublishRequest);

        Boolean update = salesPlanScItemExtendRepository.editSalesPlanScItemExtend(salesPlanPublishSDO);
        if (update) {
            return Result.success(salesPlanScItemExtendRepository.queryById(editSalesPlanPublishRequest.getId()));
        }
        return null;
    }

    private void editSalesPlanPublishRequestConverter(SalesPlanScItemExtendSDO originSdo, EditSalesPlanPublishRequest editRequest) {
        SalesPlanSDO salesPlan = salesPlanCommonService.checkSalesPlan(originSdo.getPlanId());
//        if (!SalesPlanStatusEnum.TO_BE_PUBLISHED.getCode().equals(salesPlan.getStatus())) {
//            throw new FacadeException("OTS-02-004-01-15-004");
//        }
        if ((editRequest.getMonthFirstTaskCount() + editRequest.getMonthMiddleTaskCount() + editRequest.getMonthLastTaskCount()) != editRequest.getTaskCount()) {
            throw new FacadeException("OTS-02-004-01-15-032");
        }
        //上旬任务量
        originSdo.setMonthFirstTaskCount(editRequest.getMonthFirstTaskCount());
        //中旬任务量
        originSdo.setMonthMiddleTaskCount(editRequest.getMonthMiddleTaskCount());
        //下旬任务量
        originSdo.setMonthLastTaskCount(editRequest.getMonthLastTaskCount());

        //任务量
        originSdo.setTaskCount(originSdo.getMonthFirstTaskCount() + originSdo.getMonthMiddleTaskCount() + originSdo.getMonthLastTaskCount());
        originSdo.setBeforeTaskMoney(originSdo.getTaskCount() * originSdo.getCostInsuranceFreight());
        //计算折后任务金额
        originSdo.calculateTaskMoney(salesPlan.getEstimateDiscount());
        originSdo.calculateTaskSatisfaction();
    }

    /**
     * 部门任务量校验触发条件：部门任务量编辑、触发失焦保存时
     * 校验规则：系统校验货品的各部门任务量总和是否小于等于该货品的公司回复量
     * 触发动作：
     * 1.对超出回复量的货品，toast提示“当前货品的部门任务量超量**件，请重新编辑”；
     * 2.当前行页面失焦保存失败，当前明细编辑回显原值（其他已保存明细不变
     *
     * @param salesPlanPublishSDO
     * @param editSalesPlanPublishRequest
     */
    private void checkDepartmentTaskCount(SalesPlanScItemExtendSDO salesPlanPublishSDO, EditSalesPlanPublishRequest editSalesPlanPublishRequest) {
        // 拿到货品
        // 查询该月度计划下该货品的所有部门回复量并汇总,修改的这条要记得替换
        // 查询该月度计划下该货品的分子公司的回复量
        // 比较所有部门回复量汇总值和分子公司的回复量并抛出对应的异常提示货品超了多少件
        String scItemId = salesPlanPublishSDO.getScItemId();
        if (StringUtils.isBlank(scItemId)) {
            throw new FacadeException("OTS-02-004-01-15-027");
        }
        String planId = salesPlanPublishSDO.getPlanId();

        QueryPlanScItemExtendRequest queryPlanScItemExtendRequest = new QueryPlanScItemExtendRequest();
        queryPlanScItemExtendRequest.setScItemId(scItemId);
        queryPlanScItemExtendRequest.setPlanId(Long.valueOf(planId));
        queryPlanScItemExtendRequest.setBizType(SalesStatBizTypeEnum.SALES_DEPARTMENT.getBizType());
        queryPlanScItemExtendRequest.setPoolType(Objects.toString(StatPoolTypeEnum.SC_ITEM.getPoolType()));
        queryPlanScItemExtendRequest.setModel(SalesPlanModelEnum.PLAN_MODEL.getModel());
        List<SalesPlanScItemExtendSDO> salesPlanScItemExtendSDOList = salesPlanScItemExtendRepository.batchQueryPlanScItemExtend(queryPlanScItemExtendRequest);

        Long id = editSalesPlanPublishRequest.getId();
        // 筛选编辑之外的数据
        List<SalesPlanScItemExtendSDO> collect = salesPlanScItemExtendSDOList
                .stream().filter(salesPlanScItemExtendSDO -> !id.equals(salesPlanScItemExtendSDO.getId())).collect(Collectors.toList());
        // 编辑的数据塞进去
        collect.add(salesPlanPublishSDO);
        // 计算部门任务量总和
        Integer taskCountByAllDepartment = collect.stream().map(SalesPlanScItemExtendSDO::getTaskCount).reduce(Integer::sum).get();

        // 查询公司任务量
        QueryPlanScItemExtendRequest queryPlanScItemExtendRequestForCompany = new QueryPlanScItemExtendRequest();
        queryPlanScItemExtendRequestForCompany.setScItemId(scItemId);
        queryPlanScItemExtendRequestForCompany.setPlanId(Long.valueOf(planId));
        queryPlanScItemExtendRequestForCompany.setBizType(SalesStatBizTypeEnum.BUSINESS_UNIT.getBizType());
        queryPlanScItemExtendRequestForCompany.setPoolType(Objects.toString(StatPoolTypeEnum.SC_ITEM.getPoolType()));
        queryPlanScItemExtendRequestForCompany.setModel(SalesPlanModelEnum.PLAN_MODEL.getModel());
        List<SalesPlanScItemExtendSDO> salesPlanScItemExtendSDOListForCompany = salesPlanScItemExtendRepository.batchQueryPlanScItemExtend(queryPlanScItemExtendRequestForCompany);
        if (CollectionUtils.isEmpty(salesPlanScItemExtendSDOListForCompany)) {
            throw new FacadeException(ErrorMessage.code("OTS-02-004-01-15-028"));
        }
        SalesPlanScItemExtendSDO salesPlanScItemExtendSDOForCompany = salesPlanScItemExtendSDOListForCompany.get(0);
        Integer monthFirstReturnCount = salesPlanScItemExtendSDOForCompany.getMonthFirstReturnCount();
        Integer monthMiddleReturnCount = salesPlanScItemExtendSDOForCompany.getMonthMiddleReturnCount();
        Integer monthLastReturnCount = salesPlanScItemExtendSDOForCompany.getMonthLastReturnCount();
        Integer taskCount = monthFirstReturnCount + monthMiddleReturnCount + monthLastReturnCount;
        log.info("公司任务量{}", JSON.toJSONString(taskCount));
        log.info("编辑部门任务量对应所有部门任务量总和{}", JSON.toJSONString(taskCountByAllDepartment));
        //超量回复迭代 不校验任务量
//        if (taskCount < taskCountByAllDepartment) {
//            // 超量值
//            int i = taskCountByAllDepartment - taskCount;
//            throw new FacadeException(ErrorMessage.code("OTS-02-004-01-15-029", i));
//        }
    }

    /**
     * 发布部门任务量
     *
     * @param dispatchPlanScItemRequest
     * @return
     */
    @Override
    @FacadeInvoker
    @CommonRedisLock(redisLockPrefix = SalesPlanLockKey.PUBLISH_PLAN_SC_ITEM_DEPARTMENT_PREFIX)
    @EpochTransactional(appCode="bc_order", dataSourceCode = "cr_ots", dataSourceType = "app")
    public Result<Boolean> publishPlanScItemForDepartment(DispatchPlanScItemRequest dispatchPlanScItemRequest) {
        // 0、参数校验
        checkParam(dispatchPlanScItemRequest);
        // 1、根据计划id查询  计划是否是待发布状态 否 直接抛异常 (20220915去掉校验)
        String planId = dispatchPlanScItemRequest.getPlanId();
        SalesPlanSDO salesPlanSDO = salesPlanCommonService.checkSalesPlan(planId);
//        Integer status = salesPlanSDO.getStatus();
//        if (!SalesPlanStatusEnum.TO_BE_PUBLISHED.getCode().equals(status)) {
//            throw new ActivityException("OTS-02-004-01-15-004");
//        }
        // 查询部门下的货品量数据
        List<Integer> statusList = Lists.newArrayList(SalesPlanStatusEnum.TO_BE_PUBLISHED.getCode(),SalesPlanStatusEnum.PUBLISHED.getCode());
        List<SalesPlanScItemExtendSDO> salesPlanScItemExtendSDOList = salesPlanCommonService.fetchPlanScItemExtendForDepartment(planId, statusList);
        // TODO 后续可优化为批量更新
        salesPlanScItemExtendSDOList.forEach(salesPlanScItemExtendSDO -> {
            salesPlanScItemExtendSDO.setStatus(SalesPlanStatusEnum.PUBLISHED.getCode());
            salesPlanScItemExtendRepository.editSalesPlanScItemExtend(salesPlanScItemExtendSDO);
        });
        // 更新发布状态为已发布部门任务量
        SalesPlanSDO updateCheckStatusSalesPlanSDO = new SalesPlanSDO();
        updateCheckStatusSalesPlanSDO.setId(Long.valueOf(planId));
        updateCheckStatusSalesPlanSDO.setCheckStatus(SalesPlanCheckStatusEnum.PUBLISH_DEPARTMENT_TASK.getCode());
        salesPlanRepository.editSalesPlan(updateCheckStatusSalesPlanSDO);
        return Result.success(true);
    }

    /**
     * 重置部门任务量
     * 暂时不使用
     * @param request
     * @return
     */
    @Override
    @FacadeInvoker
    @EpochTransactional(appCode="bc_order", dataSourceCode = "cr_ots", dataSourceType = "app")
    @CommonRedisLock(redisLockPrefix = SalesPlanLockKey.RESET_PLAN_SC_ITEM_DEPARTMENT_PREFIX)
    public Result<Boolean> resetPlanScItemForDepartment(DispatchPlanScItemRequest request) {
        // 1、查询计划
        SalesPlanSDO salesPlan = checkPlan(request.getPlanId());

        // 2、查询分子公司的货品回复量
        QueryPlanScItemExtendRequest queryPlanScItemExtendRequest = new QueryPlanScItemExtendRequest();
        queryPlanScItemExtendRequest.setPlanId(Long.valueOf(request.getPlanId()));
        queryPlanScItemExtendRequest.setBizType(SalesStatBizTypeEnum.SALES_DEPARTMENT.getBizType());
        queryPlanScItemExtendRequest.setPoolType(Objects.toString(StatPoolTypeEnum.SC_ITEM.getPoolType()));
        queryPlanScItemExtendRequest.setStatus(SalesPlanStatusEnum.TO_BE_PUBLISHED.getCode());
        List<SalesPlanScItemExtendSDO> salesPlanScItemExtendSDOList = salesPlanScItemExtendRepository.batchQueryPlanScItemExtend(queryPlanScItemExtendRequest);
        if (CollectionUtils.isEmpty(salesPlanScItemExtendSDOList)) {
            throw new FacadeException("OTS-02-004-01-15-005");
        }
        for (SalesPlanScItemExtendSDO extend : salesPlanScItemExtendSDOList) {
            extend.setMonthFirstTaskCount(extend.getMonthFirstReturnCount());
            extend.setMonthMiddleTaskCount(extend.getMonthMiddleReturnCount());
            extend.setMonthLastTaskCount(extend.getMonthLastReturnCount());
            extend.setTaskCount(extend.getMonthFirstReturnCount() + extend.getMonthMiddleReturnCount() + extend.getMonthLastReturnCount());
            extend.setBeforeTaskMoney(extend.getTaskCount() * extend.getCostInsuranceFreight());
            //计算折后任务金额
            extend.calculateTaskMoney(salesPlan.getEstimateDiscount());
            extend.calculateTaskSatisfaction();
            salesPlanScItemExtendRepository.editSalesPlanScItemExtend(extend);
        }
        return Result.success(true);
    }

    /**
     * 校验计划
     *
     * @param planId
     * @return
     */
    private SalesPlanSDO checkPlan(String planId) {
        QuerySalesPlanRequest querySalesPlanRequest = new QuerySalesPlanRequest();
        querySalesPlanRequest.setId(planId);
        SalesPlanSDO salesPlanSDO = salesPlanRepository.load(querySalesPlanRequest);
        if (Objects.isNull(salesPlanSDO)) {
            throw new FacadeException("OTS-02-002-00-16-001");
        }
        Integer status = salesPlanSDO.getStatus();
        if (!SalesPlanStatusEnum.TO_BE_PUBLISHED.getCode().equals(status)) {
            throw new FacadeException("OTS-02-004-01-15-004");
        }
        return salesPlanSDO;
    }

    /**
     * 客户任务量失焦保存
     *
     * @param editSalesPlanDetailRequest
     * @return
     */
    @Override
    @FacadeInvoker
    @CommonRedisLock(redisLockPrefix = SalesPlanLockKey.EDIT_SALES_PLAN_DETAIL_PREFIX)
    public Result<SalesPlanLineSDO> editSalesPlanDetail(EditSalesPlanPublishRequest editSalesPlanDetailRequest) {
        QuerySalesPlanLineRequest querySalesPlanLineRequest = new QuerySalesPlanLineRequest();
        querySalesPlanLineRequest.setId(editSalesPlanDetailRequest.getId());
        SalesPlanLineSDO salesPlanLineSDO = salesPlanLineRepository.querySalesPlanLine(querySalesPlanLineRequest);
        if (salesPlanLineSDO == null) {
            throw new FacadeException("OTS-02-004-01-15-031");
        }
        editSalesPlanDetailRequestConverter(salesPlanLineSDO, editSalesPlanDetailRequest);

        // 校验任务量
        checkCustomerTaskCount(salesPlanLineSDO, editSalesPlanDetailRequest);

        Integer edit = salesPlanLineRepository.edit(salesPlanLineSDO);
        if (edit > 0) {
            return Result.success(salesPlanLineRepository.querySalesPlanLine(querySalesPlanLineRequest));
        }
        return null;
    }

    @Override
    @ProcessInvoker
    @CommonRedisLock(redisLockPrefix = SalesPlanLockKey.EDIT_SALES_PLAN_DETAIL_IMPORT_PREFIX)
    public Result<SalesPlanLineSDO> editSalesPlanDetailForImport(EditSalesPlanPublishRequest editSalesPlanDetailRequest) {
        QuerySalesPlanLineRequest querySalesPlanLineRequest = new QuerySalesPlanLineRequest();
        querySalesPlanLineRequest.setId(editSalesPlanDetailRequest.getId());
        SalesPlanLineSDO salesPlanLineSDO = salesPlanLineRepository.querySalesPlanLine(querySalesPlanLineRequest);
        if (salesPlanLineSDO == null) {
            throw new FacadeException("OTS-02-004-01-15-031");
        }
        editSalesPlanDetailRequestConverter(salesPlanLineSDO, editSalesPlanDetailRequest);

        //校验任务量
//        checkCustomerTaskCount(salesPlanLineSDO, editSalesPlanDetailRequest);

        Integer edit = salesPlanLineRepository.edit(salesPlanLineSDO);
        if (edit > 0) {
            return Result.success(salesPlanLineRepository.querySalesPlanLine(querySalesPlanLineRequest));
        }
        return null;
    }

    private void editSalesPlanDetailRequestConverter(SalesPlanLineSDO originSdo, EditSalesPlanPublishRequest editRequest) {
        SalesPlanSDO salesPlan = salesPlanCommonService.checkSalesPlan(originSdo.getPlanId());
//        if (!SalesPlanStatusEnum.TO_BE_PUBLISHED.getCode().equals(salesPlan.getStatus())) {
//            throw new FacadeException("OTS-02-004-01-15-004");
//        }
        if ((editRequest.getMonthFirstTaskCount() + editRequest.getMonthMiddleTaskCount() + editRequest.getMonthLastTaskCount()) != editRequest.getTaskCount()) {
            throw new FacadeException("OTS-02-004-01-15-032");
        }
        //上旬任务量
        originSdo.setMonthFirstTaskCount(editRequest.getMonthFirstTaskCount());
        //中旬任务量
        originSdo.setMonthMiddleTaskCount(editRequest.getMonthMiddleTaskCount());
        //下旬任务量
        originSdo.setMonthLastTaskCount(editRequest.getMonthLastTaskCount());

        //任务量
        originSdo.setTaskCount(originSdo.getMonthFirstTaskCount() + originSdo.getMonthMiddleTaskCount() + originSdo.getMonthLastTaskCount());
        originSdo.setBeforeTaskMoney(originSdo.getTaskCount() * originSdo.getCostInsuranceFreight());
        //计算折后任务金额
        originSdo.calculateTaskMoney(salesPlan.getEstimateDiscount());
        originSdo.calculateTaskSatisfaction();
        originSdo.setGmtModified(new Date());
    }

    /**
     * 客户任务量校验触发条件：客户任务量编辑、触发失焦保存时
     * 校验规则：系统校验货品的各客户任务量总和是否小于等于该货品的部门回复量
     * 触发动作：
     * 1.对超出回复量的货品，toast提示“当前货品的客户任务量超量**件，请重新编辑”；
     * 2.当前行页面失焦保存失败，当前明细编辑回显原值（其他已保存明细不变）
     *
     * @param salesPlanLineSDO
     * @param editSalesPlanDetailRequest
     */
    private void checkCustomerTaskCount(SalesPlanLineSDO salesPlanLineSDO, EditSalesPlanPublishRequest editSalesPlanDetailRequest) {
        // 拿到货品
        // 查询该月度计划下该货品的所有客户回复量并汇总,修改的这条要记得替换
        // 查询该月度计划下该货品的部门的回复量
        // 比较所有客户回复量汇总值和部门的回复量并抛出对应的异常提示货品超了多少件
        String scItemId = salesPlanLineSDO.getScItemId();
        if (StringUtils.isBlank(scItemId)) {
            throw new FacadeException("OTS-02-004-01-15-039");
        }
        String planId = salesPlanLineSDO.getPlanId();
        // 得到修改的客户所属的部门
        String orgSalesDepartmentCode = salesPlanLineSDO.getOrgSalesDepartmentCode();

        SalesPlanBatchQueryRequest salesPlanBatchQueryRequest = new SalesPlanBatchQueryRequest();
        salesPlanBatchQueryRequest.setScItemId(scItemId);
        salesPlanBatchQueryRequest.setPlanId(Long.valueOf(planId));
        salesPlanBatchQueryRequest.setOrgSalesDepartmentCode(orgSalesDepartmentCode);
        List<SalesPlanLineSDO> salesPlanLineSDOList = salesPlanLineRepository.batchQueryDetail(salesPlanBatchQueryRequest);
        // 状态为-1的删除数据剔除
        List<SalesPlanLineSDO> salesPlanLineSDOList1 = salesPlanLineSDOList.stream().filter(salesPlanLineSDO1 -> salesPlanLineSDO1.getStatus() != -1).collect(Collectors.toList());

        Long id = editSalesPlanDetailRequest.getId();
        // 筛选编辑之外的数据
        List<SalesPlanLineSDO> collect = salesPlanLineSDOList1
                .stream().filter(salesPlanLine -> !id.equals(salesPlanLine.getId())).collect(Collectors.toList());
        // 编辑的数据塞进去
        collect.add(salesPlanLineSDO);
        // 计算客户任务量总和
        Integer taskCountByAllCustomer = collect.stream().map(SalesPlanLineSDO::getTaskCount).reduce(Integer::sum).get();

        // 获取部门任务量
        QueryPlanScItemExtendRequest queryPlanScItemExtendRequest = new QueryPlanScItemExtendRequest();
        queryPlanScItemExtendRequest.setScItemId(scItemId);
        queryPlanScItemExtendRequest.setPlanId(Long.valueOf(planId));
        queryPlanScItemExtendRequest.setBizType(SalesStatBizTypeEnum.SALES_DEPARTMENT.getBizType());
        queryPlanScItemExtendRequest.setBizId(orgSalesDepartmentCode);
        queryPlanScItemExtendRequest.setPoolType(Objects.toString(StatPoolTypeEnum.SC_ITEM.getPoolType()));
        queryPlanScItemExtendRequest.setModel(SalesPlanModelEnum.PLAN_MODEL.getModel());
        List<SalesPlanScItemExtendSDO> salesPlanScItemExtendSDOList = salesPlanScItemExtendRepository.batchQueryPlanScItemExtend(queryPlanScItemExtendRequest);
        if (CollectionUtils.isEmpty(salesPlanScItemExtendSDOList)) {
            throw new FacadeException("OTS-02-004-01-15-040");
        }
        SalesPlanScItemExtendSDO salesPlanScItemExtendSDO = salesPlanScItemExtendSDOList.get(0);
        Integer taskCountByDepartment = salesPlanScItemExtendSDO.getTaskCount();
        //超量回复迭代 不校验任务量
//        if (taskCountByDepartment < taskCountByAllCustomer) {
//            // 超量值
//            int i = taskCountByAllCustomer - taskCountByDepartment;
//            throw new FacadeException("OTS-02-004-01-15-041", i);
//        }
    }

    @Override
    @EpochTransactional(appCode = "bc_order", dataSourceCode = "cr_ots", dataSourceType = "app")
    @FacadeInvoker
    public Result<SalesPlanAdjustDetailSDO> editSalesPlanAdjustDetail(EditSalesPlanAdjustDetailRequest editSalesPlanAdjustDetailRequest) {
        QueryPlanAdjustDetailRequest queryPlanAdjustDetailRequest = new QueryPlanAdjustDetailRequest();
        queryPlanAdjustDetailRequest.setId(editSalesPlanAdjustDetailRequest.getId());
        SalesPlanAdjustDetailSDO salesPlanAdjustDetailSDO = salesPlanAdjustDetailRepository.querySalesPlanAdjustDetailList(queryPlanAdjustDetailRequest);
        if (Objects.isNull(salesPlanAdjustDetailSDO)) {
            throw new FacadeException("OTS-02-005-00-15-003");
        }

        //导入的先跳过校验
        if (!editSalesPlanAdjustDetailRequest.getIsImport()) {
            log.info("editSalesPlanAdjustDetail.salesPlanAdjustDetailSDO" + JSONObject.toJSONString(salesPlanAdjustDetailSDO));
            Result<SalesPlanAdjustDetailSDO> checkResult = checkAdjustReturnCount(salesPlanAdjustDetailSDO, editSalesPlanAdjustDetailRequest);
            log.info("editSalesPlanAdjustDetail.checkResult" + JSONObject.toJSONString(checkResult));
            if (!checkResult.isSuccess()) {
                return checkResult;
            }
        }

        SalesPlanAdjustDetailSDO editSdo = editSalesPlanRequestConverter(salesPlanAdjustDetailSDO, editSalesPlanAdjustDetailRequest);
        SalesPlanAdjustDetailEntity salesPlanLineEntity = SalesPlanAdjustDetailEntity.of(editSdo);
        Integer count = salesPlanLineEntity.doEdit();
        if (count > 0) {
            if (editSdo.getPlanDetailId() != null) {
                //更新月度计划明细
                UpdateAdjustCountRequest updateAdjustCountRequest = new UpdateAdjustCountRequest();
                updateAdjustCountRequest.setId(editSdo.getPlanDetailId());
                updateAdjustCountRequest.setAdjustCount(editSdo.getAdjustCount());
                updateAdjustCountRequest.setAdjustMoney(editSdo.getAdjustMoney());
                updateAdjustCountRequest.setBeforeAdjustMoney(editSdo.getBeforeAdjustMoney());
                updateAdjustCountRequest.setMonthFirstAdjustCount(editSdo.getMonthFirstAdjustCount());
                updateAdjustCountRequest.setMonthMiddleAdjustCount(editSdo.getMonthMiddleAdjustCount());
                updateAdjustCountRequest.setMonthLastAdjustCount(editSdo.getMonthLastAdjustCount());
                updateAdjustCountRequest.setMonthFirstAdjustReturnCount(editSdo.getMonthFirstAdjustReturnCount());
                updateAdjustCountRequest.setMonthMiddleAdjustReturnCount(editSdo.getMonthMiddleAdjustReturnCount());
                updateAdjustCountRequest.setMonthLastAdjustReturnCount(editSdo.getMonthLastAdjustReturnCount());
                salesPlanLineWriteService.updateAdjustCount(updateAdjustCountRequest);
            }
        }
        return Result.success(salesPlanAdjustDetailRepository.querySalesPlanAdjustDetailList(queryPlanAdjustDetailRequest));
    }

    private Result<SalesPlanAdjustDetailSDO> checkAdjustReturnCount(SalesPlanAdjustDetailSDO salesPlanAdjustDetailSDO, EditSalesPlanAdjustDetailRequest editSalesPlanAdjustDetailRequest) {
        //校验回复量是否超量
        Long id = salesPlanAdjustDetailSDO.getId();
        Long adjustId = salesPlanAdjustDetailSDO.getAdjustId();
        String scItemId = salesPlanAdjustDetailSDO.getScItemId();
        Integer taskCount = salesPlanAdjustDetailSDO.getTaskCount();
        if (null == adjustId || null == scItemId || null == id || null == taskCount) {
            log.info("checkAdjustReturnCount:adjustId或scItemId或id为空");
            return Result.fail(salesPlanAdjustDetailSDO, "OTS-02-005-00-15-032", ErrorMessage.code("OTS-02-005-00-15-032", null).getDisplayErrorMessage());
        }
        //查询公司任务量
        PlanScItemExtend planScItemExtend = null;
        try {
            BatchQueryRequest batchQueryRequest = BatchQueryRequest.builder().bizType("5").poolType("2").model("2")
                    .modelIds(Lists.newArrayList(adjustId.toString())).scItemId(scItemId).build();
            log.info("checkAdjustReturnCount.batchQueryRequest:" + JSONObject.toJSONString(batchQueryRequest));
            Result<List<PlanScItemExtend>> listResult = planScItemExtendService.batchQuery(batchQueryRequest);
            log.info("checkAdjustReturnCount:" + JSONObject.toJSONString(listResult));
            List<PlanScItemExtend> planScItemExtendList = listResult.getResult();
            if (!listResult.isSuccess() || listResult.getTotal() == ZERO || CollectionUtils.isEmpty(planScItemExtendList)) {
                return Result.fail(salesPlanAdjustDetailSDO, "OTS-02-005-00-15-033", ErrorMessage.code("OTS-02-005-00-15-033", null).getDisplayErrorMessage());
            }
            if (listResult.getTotal() != 1 || planScItemExtendList.size() != 1) {
                log.info("checkAdjustReturnCount:查询公司任务量数据错误");
            }
            planScItemExtend = planScItemExtendList.get(ZERO);
            if (Objects.isNull(planScItemExtend)) {
                return Result.fail(salesPlanAdjustDetailSDO, "OTS-02-005-00-15-033", ErrorMessage.code("OTS-02-005-00-15-033", null).getDisplayErrorMessage());
            }
            log.info("checkAdjustReturnCount:planScItemExtend" + JSONObject.toJSONString(planScItemExtend));
        } catch (Exception e) {
            log.info("checkAdjustReturnCount:查询公司任务量报错" + e);
            return Result.fail(salesPlanAdjustDetailSDO, "OTS-02-005-00-15-033", ErrorMessage.code("OTS-02-005-00-15-033", null).getDisplayErrorMessage());
        }
        //获取公司回复量
        BigDecimal companyAdjustReturnCount = getCompanyAdjustReturnCount(planScItemExtend);
        log.info("checkAdjustReturnCount:companyAdjustReturnCount=" + companyAdjustReturnCount);

        //查询客户任务量
        List<SalesPlanAdjustDetail> salesPlanAdjustDetailList = getSalesPlanAdjustDetailList(adjustId, scItemId);
        if (CollectionUtils.isEmpty(salesPlanAdjustDetailList)) {
            return Result.fail(salesPlanAdjustDetailSDO, "OTS-02-005-00-15-034", ErrorMessage.code("OTS-02-005-00-15-034", null).getDisplayErrorMessage());
        }
        //客户任务量单行校验:可调整回复量+任务量>=0
        //获取修改后的单行客户回复量
        BigDecimal singleCustomerAdjustReturnCount = getSingleCustomerAdjustReturnCount(editSalesPlanAdjustDetailRequest);
        log.info("checkAdjustReturnCount:singleCustomerAdjustReturnCount=" + singleCustomerAdjustReturnCount);
        int compareSingleCount = singleCustomerAdjustReturnCount.add(new BigDecimal(taskCount)).intValue();
        if (compareSingleCount < ZERO) {
            return Result.fail(salesPlanAdjustDetailSDO, "OTS-02-005-00-15-035", ErrorMessage.code("OTS-02-005-00-15-035", compareSingleCount).getDisplayErrorMessage());
        }

        //获取客户总回复量
        BigDecimal customerAdjustReturnCount = getCustomerAdjustReturnCount(singleCustomerAdjustReturnCount, id, salesPlanAdjustDetailList);
        log.info("checkAdjustReturnCount:customerAdjustReturnCount=" + customerAdjustReturnCount);
        //总量校验:如果回复量大于等于0，0<=可调整回复量<=回复量；如果回复量小于0，可调整回复量>=回复量
        int compareTotalCount = ZERO;
        if (companyAdjustReturnCount.compareTo(BigDecimal.ZERO) < ZERO) {
            if (customerAdjustReturnCount.compareTo(companyAdjustReturnCount) >= ZERO) {
                return Result.success(salesPlanAdjustDetailSDO);
            }
            compareTotalCount = companyAdjustReturnCount.subtract(customerAdjustReturnCount).intValue();
        } else {
            if (customerAdjustReturnCount.compareTo(companyAdjustReturnCount) <= ZERO) {
                return Result.success(salesPlanAdjustDetailSDO);
            }
            compareTotalCount = customerAdjustReturnCount.subtract(companyAdjustReturnCount).intValue();
        }
        return Result.fail(salesPlanAdjustDetailSDO, "OTS-02-005-00-15-035", ErrorMessage.code("OTS-02-005-00-15-035", compareTotalCount).getDisplayErrorMessage());
    }

    @NotNull
    private List<SalesPlanAdjustDetail> getSalesPlanAdjustDetailList(Long adjustId, String scItemId) {
        List<SalesPlanAdjustDetail> salesPlanAdjustDetailList = Lists.newArrayList();
        try {
            int pageTotal = 1;
            for (int i = 0; i < pageTotal; i++) {
                BatchQueryDetailByIdsRequest batchQueryDetailByIdsRequest = BatchQueryDetailByIdsRequest.builder()
                        .adjustId(adjustId.toString()).scItemId(scItemId).start(i * LIMIT).limit(LIMIT).build();
                log.info("checkAdjustReturnCount.batchQueryDetailByIdsRequest:" + JSONObject.toJSONString(batchQueryDetailByIdsRequest));
                BatchQueryDetailByIdsResponse response = salesPlanAdjustDetailService.batchQueryDetailByIds(batchQueryDetailByIdsRequest);
                if (response == null || response.getTotal() == ZERO || CollectionUtils.isEmpty(response.getResult())) {
                    return salesPlanAdjustDetailList;
                }
                salesPlanAdjustDetailList.addAll(response.getResult());
                if (response.getTotal() == null || LIMIT >= response.getTotal()) {
                    return salesPlanAdjustDetailList;
                }
                Integer total = response.getTotal();
                pageTotal = total % LIMIT == ZERO ? total / LIMIT : total / LIMIT + 1;
            }
            return salesPlanAdjustDetailList;
        } catch (Exception e) {
            log.info("checkAdjustReturnCount.batchQueryDetailByIds:查询客户任务量报错" + e);
            return Lists.newArrayList();
        }
    }

    private BigDecimal getSingleCustomerAdjustReturnCount(EditSalesPlanAdjustDetailRequest editSalesPlanAdjustDetailRequest) {
        return new BigDecimal(editSalesPlanAdjustDetailRequest.getMonthFirstAdjustReturnCount())
                .add(new BigDecimal(editSalesPlanAdjustDetailRequest.getMonthMiddleAdjustReturnCount()))
                .add(new BigDecimal(editSalesPlanAdjustDetailRequest.getMonthLastAdjustReturnCount()));
    }

    private BigDecimal getCustomerAdjustReturnCount(BigDecimal singleCustomerAdjustReturnCount, Long id, List<SalesPlanAdjustDetail> salesPlanAdjustDetailList) {
        BigDecimal sum = BigDecimal.ZERO;
        if (singleCustomerAdjustReturnCount.compareTo(BigDecimal.ZERO) != ZERO) {
            sum = sum.add(singleCustomerAdjustReturnCount);
        }
        //过滤掉修改前的数据
        salesPlanAdjustDetailList = salesPlanAdjustDetailList.stream()
                .filter(salesPlanAdjustDetail -> !id.equals(salesPlanAdjustDetail.getId()))
                .collect(Collectors.toList());
        Integer adjustReturnCount = salesPlanAdjustDetailList.stream().map(x ->
                new BigDecimal(x.getMonthFirstAdjustReturnCount())
                        .add(new BigDecimal(x.getMonthMiddleAdjustReturnCount()))
                        .add(new BigDecimal(x.getMonthLastAdjustReturnCount())).intValue())
                .reduce(Integer::sum).orElse(ZERO);
        if (adjustReturnCount != ZERO) {
            sum = sum.add(new BigDecimal(adjustReturnCount));
        }
        return sum;
    }

    private BigDecimal getCompanyAdjustReturnCount(PlanScItemExtend planScItemExtend) {
        BigDecimal sum = BigDecimal.ZERO;
        if (planScItemExtend.getMonthFirstAdjustReturnCount() != null && planScItemExtend.getMonthFirstAdjustReturnCount() != ZERO) {
            sum = sum.add(new BigDecimal(planScItemExtend.getMonthFirstAdjustReturnCount()));
        }
        if (planScItemExtend.getMonthMiddleAdjustReturnCount() != null && planScItemExtend.getMonthMiddleAdjustReturnCount() != ZERO) {
            sum = sum.add(new BigDecimal(planScItemExtend.getMonthMiddleAdjustReturnCount()));
        }
        if (planScItemExtend.getMonthLastAdjustReturnCount() != null && planScItemExtend.getMonthLastAdjustReturnCount() != ZERO) {
            sum = sum.add(new BigDecimal(planScItemExtend.getMonthLastAdjustReturnCount()));
        }
        return sum;
    }

    private SalesPlanAdjustDetailSDO editSalesPlanRequestConverter(SalesPlanAdjustDetailSDO salesPlanAdjustDetailSDO, EditSalesPlanAdjustDetailRequest editSalesPlanAdjustDetailRequest) {
        // 构建失焦保存的sdo
        SalesPlanAdjustDetailSDO editSdo = SalesPlanAdjustDetailSDO.builder().build();
        BeanUtils.copyProperties(salesPlanAdjustDetailSDO, editSdo);

        Long adjustId = salesPlanAdjustDetailSDO.getAdjustId();
        QuerySalesPlanRequest querySalesPlanRequest = new QuerySalesPlanRequest();
        querySalesPlanRequest.setId(adjustId.toString());
        Result<SalesPlanSDO> salesPlan = salesPlanQueryService.getSalesPlan(querySalesPlanRequest);
        SalesPlanSDO salesPlanSDO = salesPlan.getResult();
        if (Objects.isNull(salesPlanSDO)) {
            throw new FacadeException("OTS-02-002-00-16-001");
        }
        //根据调整计划设置修改上中下旬的值
        if (Optional.ofNullable(salesPlanSDO.getMonthFirst()).orElse(true)) {
            //上旬调整回复量
            editSdo.setMonthFirstAdjustReturnCount(Optional.ofNullable(editSalesPlanAdjustDetailRequest.getMonthFirstAdjustReturnCount()).orElse(0));
        }
        if (Optional.ofNullable(salesPlanSDO.getMonthMiddle()).orElse(true)) {
            //中旬调整回复量
            editSdo.setMonthMiddleAdjustReturnCount(Optional.ofNullable(editSalesPlanAdjustDetailRequest.getMonthMiddleAdjustReturnCount()).orElse(0));
        }
        if (Optional.ofNullable(salesPlanSDO.getMonthLast()).orElse(true)) {
            //下旬调整回复量
            editSdo.setMonthLastAdjustReturnCount(Optional.ofNullable(editSalesPlanAdjustDetailRequest.getMonthLastAdjustReturnCount()).orElse(0));
        }

        //调整回复量
        Integer monthAdjustReturnCount = editSdo.getMonthFirstAdjustReturnCount() + editSdo.getMonthMiddleAdjustReturnCount() + editSdo.getMonthLastAdjustReturnCount();
        //按照发布后的计算逻辑
        Long costInsuranceFreight = Optional.ofNullable(editSdo.getCostInsuranceFreight()).orElse(0L);
        BigDecimal estimateDiscount = Optional.ofNullable(salesPlanSDO.getEstimateDiscount()).orElse(new BigDecimal(0));
        //发布后计算逻辑
        //计算折前折后满足度
        editSdo.calculateTaskReturnSatisfaction(costInsuranceFreight, estimateDiscount);
        //计算折前折后任务金额
        editSdo.calculateTaskReturnMoney(costInsuranceFreight, estimateDiscount);
        //到岸折前金额=（任务数量+调整回复数量）*到岸价
        long outboundPrice = Objects.nonNull(editSdo.getOutboundPrice()) ? editSdo.getOutboundPrice() : 0;
        long beforeMonthOutboundMoney = (editSdo.getTaskCount() + monthAdjustReturnCount) * outboundPrice;
        editSdo.setBeforeMonthOutboundMoney(beforeMonthOutboundMoney);
        //到岸折后金额 到岸折后金额=到岸折前金额*(1-预估价格折扣率)
        editSdo.calculateMonthOutboundMoney(salesPlanSDO.getEstimateDiscount());
        editSdo.setGmtModified(new Date());
        return editSdo;
    }

    @Override
    @FacadeInvoker
    public Result<String> batchImportCreateSalesPlanTaskAdjustDetail(List<SalesPlanAdjustDetailSDO> salesPlanAdjustDetailSDOList) {
        if (org.apache.commons.collections.CollectionUtils.isEmpty(salesPlanAdjustDetailSDOList)) {
            throw new FacadeException("OTS-02-002-02-15-013");
        }

        // adjustId+客户收收获地址编码+货品编码查询重复数据，重复则更新，否则新增
        Set<Long> adjustIdSet = salesPlanAdjustDetailSDOList.stream().map(SalesPlanAdjustDetailSDO::getAdjustId).collect(Collectors.toSet());
        Set<String> customerAddresSet = salesPlanAdjustDetailSDOList.stream().map(SalesPlanAdjustDetailSDO::getCustomerAddress).collect(Collectors.toSet());
        Set<String> scItemIdSet = salesPlanAdjustDetailSDOList.stream().map(SalesPlanAdjustDetailSDO::getScItemId).collect(Collectors.toSet());
        Set<String> customerAddressIdSet = salesPlanAdjustDetailSDOList.stream().map(SalesPlanAdjustDetailSDO::getCustomerAddressId).filter(StringUtils::isNotBlank).collect(Collectors.toSet());

        SalesPlanAdjustDetailBatchQueryRequest salesPlanAdjustDetailBatchQueryRequest = new SalesPlanAdjustDetailBatchQueryRequest();
        salesPlanAdjustDetailBatchQueryRequest.setAdjustIds(Lists.newArrayList(adjustIdSet));
        salesPlanAdjustDetailBatchQueryRequest.setCustomerAddress(Lists.newArrayList(customerAddresSet));
        salesPlanAdjustDetailBatchQueryRequest.setScItemIds(Lists.newArrayList(scItemIdSet));
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(customerAddressIdSet)) {
            salesPlanAdjustDetailBatchQueryRequest.setCustomerAddressId(Lists.newArrayList(customerAddressIdSet));
        }
        Map<String, SalesPlanAdjustDetailSDO> salesPlanAdjustMap = salesPlanAdjustDetailRepository.batchQueryDetail(salesPlanAdjustDetailBatchQueryRequest).stream()
                .collect(Collectors.toMap(x -> {
                    StringBuilder builder = new StringBuilder(x.getAdjustId().toString());
                    if (StringUtils.isNotBlank(x.getCustomerAddressId())) {
                        builder.append(x.getCustomerAddressId());
                    }
                    builder.append(x.getCustomerAddress()).append(x.getScItemId());
                    return builder.toString();
                }, a -> a, (a, b) -> a));

        //新增
        List<SalesPlanAdjustDetailSDO> batchCreateRequestList = new ArrayList<>();
        //修改
        List<SalesPlanAdjustDetailSDO> batchEditRequestList = new ArrayList<>();
        for (SalesPlanAdjustDetailSDO adjustDetailSDO : salesPlanAdjustDetailSDOList) {
            StringBuilder builder = new StringBuilder(adjustDetailSDO.getAdjustId().toString());
            if (StringUtils.isNotBlank(adjustDetailSDO.getCustomerAddressId())) {
                builder.append(adjustDetailSDO.getCustomerAddressId());
            }
            builder.append(adjustDetailSDO.getCustomerAddress()).append(adjustDetailSDO.getScItemId());
            String key = builder.toString();
            SalesPlanAdjustDetailSDO salesPlanAdjustDetailSDO = salesPlanAdjustMap.get(key);
            if (Objects.isNull(salesPlanAdjustDetailSDO)) {
                batchCreateRequestList.add(adjustDetailSDO);
            } else {
                Integer adjustCount = Optional.ofNullable(adjustDetailSDO.getAdjustCount()).orElse(0);
                Integer monthFirstAdjustCount = Optional.ofNullable(adjustDetailSDO.getMonthFirstAdjustCount()).orElse(0);
                Integer monthMiddleAdjustCount = Optional.ofNullable(adjustDetailSDO.getMonthMiddleAdjustCount()).orElse(0);
                Integer monthLastAdjustCount = Optional.ofNullable(adjustDetailSDO.getMonthLastAdjustCount()).orElse(0);
                Integer monthFirstAdjustReturnCount = Optional.ofNullable(adjustDetailSDO.getMonthFirstAdjustReturnCount()).orElse(0);
                Integer monthMiddleAdjustReturnCount = Optional.ofNullable(adjustDetailSDO.getMonthMiddleAdjustReturnCount()).orElse(0);
                Integer monthLastAdjustReturnCount = Optional.ofNullable(adjustDetailSDO.getMonthLastAdjustReturnCount()).orElse(0);
                BeanUtils.copyProperties(salesPlanAdjustDetailSDO, adjustDetailSDO);
                adjustDetailSDO.setAdjustCount(adjustCount);
                adjustDetailSDO.setMonthFirstAdjustCount(monthFirstAdjustCount);
                adjustDetailSDO.setMonthMiddleAdjustCount(monthMiddleAdjustCount);
                adjustDetailSDO.setMonthLastAdjustCount(monthLastAdjustCount);
                adjustDetailSDO.setMonthFirstAdjustReturnCount(monthFirstAdjustReturnCount);
                adjustDetailSDO.setMonthMiddleAdjustReturnCount(monthMiddleAdjustReturnCount);
                adjustDetailSDO.setMonthLastAdjustReturnCount(monthLastAdjustReturnCount);
                batchEditRequestList.add(adjustDetailSDO);
            }
        }
        int count = 0;
        if (batchCreateRequestList.size() > 0) {
            //添加月度计划明细
            List<SalesPlanLineSDO> salesPlanLineSDOList = batchCreateRequestList.stream().map(salesPlanAdjustDetailSDO -> {
                SalesPlanLineSDO salesPlanLineSDO = SalesPlanLineSDO.builder().build();
                BeanUtils.copyProperties(salesPlanAdjustDetailSDO, salesPlanLineSDO);
                salesPlanLineSDO.setStatus(SalesPlanLineStatusEnum.ADJUST_ADD.getStatus());
                return salesPlanLineSDO;
            }).collect(Collectors.toList());
            String successCount = salesPlanLineAbility.batchCreateSalesPlanLine(salesPlanLineSDOList);
            if (Integer.parseInt(successCount) > 0) {
                //新增调整明细
                SalesPlanAdjustDetailSDO salesPlanAdjustDetailSDO1 = salesPlanAdjustDetailSDOList.stream().findFirst().get();
                PageQueryPlanLineRequest queryPlanLineRequest = new PageQueryPlanLineRequest();
                queryPlanLineRequest.setPlanId(salesPlanAdjustDetailSDO1.getPlanId());
                queryPlanLineRequest.setStatus(SalesPlanLineStatusEnum.ADJUST_ADD.getStatus());
                queryPlanLineRequest.setCustomerAddresss(Lists.newArrayList(customerAddresSet));
                if (org.apache.commons.collections.CollectionUtils.isNotEmpty(customerAddressIdSet)) {
                    queryPlanLineRequest.setCustomerAddressIdList(Lists.newArrayList(customerAddressIdSet));
                }
                queryPlanLineRequest.setScItemIds(Lists.newArrayList(scItemIdSet));
                //获取总数
                PageResult<List<SalesPlanLineSDO>> listPageResult = salesPlanLineRepository.pageQuerySalesPlanLineAdjustAddList(queryPlanLineRequest);
                int totalPage = (listPageResult.getTotal() + SALES_PLAN_LIN_PAGE_SIZE - 1) / SALES_PLAN_LIN_PAGE_SIZE;
                //调整明细数据
                List<SalesPlanAdjustDetailSDO> sdoList = new ArrayList<>();
                for (int i = 1; i <= totalPage; i++) {
                    String adjustId = batchCreateRequestList.stream().findFirst().get().getAdjustId().toString();
                    SalesPlanSDO salesPlanSDO = salesPlanCommonService.checkSalesPlan(adjustId);
                    queryPlanLineRequest.setSize(SALES_PLAN_LIN_PAGE_SIZE);
                    queryPlanLineRequest.setPage(i);
                    PageResult<List<SalesPlanLineSDO>> listPageResult2 = salesPlanLineRepository.pageQuerySalesPlanLineAdjustAddList(queryPlanLineRequest);
                    if (org.apache.commons.collections.CollectionUtils.isEmpty(listPageResult2.getContent())) {
                        break;
                    }
                    listPageResult2.getContent().forEach(salesPlanLineSDO -> {
                        SalesPlanAdjustDetailSDO salesPlanAdjustDetailSDO = SalesPlanAdjustDetailSDO.builder().build();
                        BeanUtils.copyProperties(salesPlanLineSDO, salesPlanAdjustDetailSDO);
                        salesPlanAdjustDetailSDO.setAdjustId(salesPlanAdjustDetailSDO1.getAdjustId());
                        salesPlanAdjustDetailSDO.setPlanDetailId(salesPlanLineSDO.getId());
                        salesPlanAdjustDetailSDO.setPlanId(salesPlanAdjustDetailSDO1.getPlanId());
                        salesPlanAdjustDetailSDO.setStatus(SalesPlanLineStatusEnum.FINISH.getStatus());
                        //调整新数据标识
                        SalesPlanAdjustDetailFeatures salesPlanAdjustDetailFeatures = new SalesPlanAdjustDetailFeatures();
                        salesPlanAdjustDetailFeatures.setIsHistory(false);
                        salesPlanAdjustDetailSDO.setFeatures(JSONObject.toJSONString(salesPlanAdjustDetailFeatures));
                        Long costInsuranceFreight = Optional.ofNullable(salesPlanAdjustDetailSDO.getCostInsuranceFreight()).orElse(0L);
                        BigDecimal estimateDiscount = Optional.ofNullable(salesPlanSDO.getEstimateDiscount()).orElse(new BigDecimal(0));
                        //调整回复量
                        Integer monthAdjustReturnCount = Optional.ofNullable(salesPlanLineSDO.getMonthFirstAdjustReturnCount()).orElse(0) + Optional.ofNullable(salesPlanLineSDO.getMonthMiddleAdjustReturnCount()).orElse(0) + Optional.ofNullable(salesPlanLineSDO.getMonthLastAdjustReturnCount()).orElse(0);
                        //计算折前折后满足度
                        salesPlanAdjustDetailSDO.calculateTaskReturnSatisfaction(costInsuranceFreight, estimateDiscount);
                        //计算折前折后任务金额
                        salesPlanAdjustDetailSDO.calculateTaskReturnMoney(costInsuranceFreight, estimateDiscount);
                        //到岸折前金额=（任务数量+调整回复数量）*到岸价
                        long outboundPrice = Objects.nonNull(salesPlanLineSDO.getOutboundPrice()) ? salesPlanLineSDO.getOutboundPrice() : 0;
                        long beforeMonthOutboundMoney = (salesPlanLineSDO.getTaskCount() + monthAdjustReturnCount) * outboundPrice;
                        salesPlanAdjustDetailSDO.setBeforeMonthOutboundMoney(beforeMonthOutboundMoney);
                        //到岸折后金额 到岸折后金额=到岸折前金额*(1-预估价格折扣率)
                        salesPlanAdjustDetailSDO.calculateMonthOutboundMoney(salesPlanSDO.getEstimateDiscount());
                        sdoList.add(salesPlanAdjustDetailSDO);

                    });
                }
                String s = salesPlanAdjustDetailAbility.batchCreateSalesPlanAdjustDetail(sdoList);
                count += Integer.parseInt(s);
            }
        }
        if (batchEditRequestList.size() > 0) {
            for (SalesPlanAdjustDetailSDO salesPlanAdjustDetailSDO : batchEditRequestList) {
                EditSalesPlanAdjustDetailRequest editSalesPlanAdjustDetailRequest = new EditSalesPlanAdjustDetailRequest();
                editSalesPlanAdjustDetailRequest.setId(salesPlanAdjustDetailSDO.getId().toString());
                editSalesPlanAdjustDetailRequest.setMonthFirstAdjustCount(salesPlanAdjustDetailSDO.getMonthFirstAdjustCount());
                editSalesPlanAdjustDetailRequest.setMonthMiddleAdjustCount(salesPlanAdjustDetailSDO.getMonthMiddleAdjustCount());
                editSalesPlanAdjustDetailRequest.setMonthLastAdjustCount(salesPlanAdjustDetailSDO.getMonthLastAdjustCount());
                editSalesPlanAdjustDetailRequest.setMonthFirstAdjustReturnCount(salesPlanAdjustDetailSDO.getMonthFirstAdjustReturnCount());
                editSalesPlanAdjustDetailRequest.setMonthMiddleAdjustReturnCount(salesPlanAdjustDetailSDO.getMonthMiddleAdjustReturnCount());
                editSalesPlanAdjustDetailRequest.setMonthLastAdjustReturnCount(salesPlanAdjustDetailSDO.getMonthLastAdjustReturnCount());
                editSalesPlanAdjustDetailRequest.setIsImport(true);
                editSalesPlanAdjustDetail(editSalesPlanAdjustDetailRequest);
            }
        }
        return Result.success(Integer.toString(count));
    }

    private void checkParam(DispatchPlanScItemRequest dispatchPlanScItemRequest) {
        if (StringUtils.isBlank(dispatchPlanScItemRequest.getPlanId())) {
            throw new FacadeException("OTS-02-004-01-15-001");
        }
    }

    private List<SalesPlanAdjustDetailSDO> fetchSalesPlanAdjustDetail(String adjustId, String orgBusinessCode, List<SalesPlanLineSDO> salesPlanLineSDOS) {
        int page = 1;
        List<SalesPlanAdjustDetailSDO> salesPlanAdjustDetailSDOS = Lists.newArrayList();
        PageResult<List<SalesPlanAdjustDetailSDO>> pageResult = pageFetchSalesPlanAdjustDetail(adjustId, orgBusinessCode, page);
        while (null != pageResult) {
            List<SalesPlanAdjustDetailSDO> salesPlanAdjustDetailSDOList = pageResult.getContent();
            salesPlanAdjustDetailSDOS.addAll(salesPlanAdjustDetailSDOList);
            List<Long> planDetailIdList = salesPlanAdjustDetailSDOList.stream().map(SalesPlanAdjustDetailSDO::getPlanDetailId).collect(Collectors.toList());
            SalesPlanDetailBatchQueryRequest salesPlanDetailBatchQueryRequest = new SalesPlanDetailBatchQueryRequest();
            salesPlanDetailBatchQueryRequest.setIds(planDetailIdList);
            List<SalesPlanLineSDO> salesPlanLineSDOList = salesPlanLineRepository.batchQueryDetailByIds(salesPlanDetailBatchQueryRequest);
            if (CollectionUtils.isNotEmpty(salesPlanLineSDOList)) {
                salesPlanLineSDOS.addAll(salesPlanLineSDOList);
            }
            // 已经是最后一页
            if (pageResult.getContent().size() < DEFAULT_PAGE_SIZE) {
                break;
            }
            pageResult = pageFetchSalesPlanAdjustDetail(adjustId, orgBusinessCode, ++page);
        }
        if (CollectionUtils.isEmpty(salesPlanAdjustDetailSDOS)) {
            throw new FacadeException(ErrorMessage.code("OTS-02-005-00-15-003"));
        }
        return salesPlanAdjustDetailSDOS;
    }

    private PageResult<List<SalesPlanAdjustDetailSDO>> pageFetchSalesPlanAdjustDetail(String adjustId, String orgBusinessCode, Integer page) {
        PageQueryPlanAdjustDetailRequest request = new PageQueryPlanAdjustDetailRequest();
        request.setAdjustId(adjustId);
        request.setOrgBusinessUnitCode(orgBusinessCode);
        request.setPage(page);
        request.setSize(DEFAULT_PAGE_SIZE);
        // 分页获取调整明细
        log.info("查询月度计划调整明细数据参数{}", JSON.toJSONString(request));
        PageResult<List<SalesPlanAdjustDetailSDO>> pageResult = salesPlanAdjustDetailRepository.pageQuerySalesPlanAdjustDetailList(request);
        log.info("查询月度计划调整明细数据结果{}", JSON.toJSONString(pageResult));
        if (null == pageResult || CollectionUtils.isEmpty(pageResult.getContent())) {
            return null;
        }
        return pageResult;
    }

    private void updatePlanScItemExtendTaskMoney(SalesPlanSDO salesPlanSDO, String adjustId) {
        QueryPlanScItemExtendRequest queryPlanScItemExtendRequest = new QueryPlanScItemExtendRequest();
        // 计划id
        queryPlanScItemExtendRequest.setPlanId(salesPlanSDO.getId());
        // 业务类型是调整
        queryPlanScItemExtendRequest.setModel(SalesPlanModelEnum.ADJUST_MODEL.getModel());
        // 查询维度是业务单元
        queryPlanScItemExtendRequest.setBizType(SalesStatBizTypeEnum.BUSINESS_UNIT.getBizType());
        // 查询具体的业务单元
        queryPlanScItemExtendRequest.setBizId(salesPlanSDO.getOrgBusinessUnitCode());
        // 查询具体的调整计划
        queryPlanScItemExtendRequest.setModelId(Long.parseLong(adjustId));
        List<SalesPlanScItemExtendSDO> salesPlanScItemExtendSDOList = salesPlanScItemExtendRepository.batchQueryPlanScItemExtend(queryPlanScItemExtendRequest);
        for (SalesPlanScItemExtendSDO salesPlanScItemExtendSDO : salesPlanScItemExtendSDOList) {
            SalesPlanPublishSDO salesPlanPublishSDO = SalesPlanPublishSDO.builder().build();
            BeanUtils.copyProperties(salesPlanScItemExtendSDO, salesPlanPublishSDO);
            Integer monthFirstAdjustReturnCount = salesPlanScItemExtendSDO.getMonthFirstAdjustReturnCount();
            Integer monthMiddleAdjustReturnCount = salesPlanScItemExtendSDO.getMonthMiddleAdjustReturnCount();
            Integer monthLastAdjustReturnCount = salesPlanScItemExtendSDO.getMonthLastAdjustReturnCount();
            Integer adjustReturnCount = monthFirstAdjustReturnCount + monthMiddleAdjustReturnCount + monthLastAdjustReturnCount;
            // 折前满足度=（任务量+调整提报量）*货品常规价
            Integer taskAdjustCount = salesPlanScItemExtendSDO.getTaskCount() + adjustReturnCount;
            Long costInsuranceFreight = salesPlanScItemExtendSDO.getCostInsuranceFreight();
            long notBeforeContractSatisfactionMoney = taskAdjustCount * costInsuranceFreight;
            // 折前任务金额
            long beforeContractSatisfactionMoney = salesPlanScItemExtendSDO.getTaskCount() * costInsuranceFreight;
            salesPlanPublishSDO.setBeforeTaskMoney(beforeContractSatisfactionMoney);
            BigDecimal beforeContractSatisfaction = CalculatePercentage.retainTwo(notBeforeContractSatisfactionMoney, salesPlanScItemExtendSDO.getBeforeMonthContractMoney());
            salesPlanPublishSDO.setBeforeContractSatisfaction(beforeContractSatisfaction);
            // 折后满足度=（任务量+调整提报量）*货品常规价*（1-预估价格折扣率）
            BigDecimal multiply = salesPlanSDO.getEstimateDiscount().multiply(new BigDecimal("0.01").setScale(2, RoundingMode.HALF_UP));
            BigDecimal subtract = new BigDecimal(1).subtract(multiply);
            BigDecimal ContractSatisfactionMoney = new BigDecimal(taskAdjustCount).multiply(new BigDecimal(costInsuranceFreight)).multiply(subtract);
            // 折后任务金额
            salesPlanPublishSDO.calculateTaskMoney(salesPlanSDO.getEstimateDiscount());
            BigDecimal contractSatisfaction = CalculatePercentage.retainTwoBigDecimal(ContractSatisfactionMoney, new BigDecimal(salesPlanScItemExtendSDO.getMonthContractMoney()));
            salesPlanPublishSDO.setContractSatisfaction(contractSatisfaction);
            salesPlanScItemExtendRepository.edit(salesPlanPublishSDO);
        }
    }
}
